#ifndef SCAN_THREAD_H
#define SCAN_THREAD_H

#include <QObject>
#include<QThread>
#include<QMutex>
#include<bits/stdc++.h>
#include<QTcpSocket>
#include<QUdpSocket>
#include<QWaitCondition>
#include<QTime>
class scan_thread:public QThread
{
    Q_OBJECT
public:
    scan_thread();
    static QMutex *mutex;
    static QWaitCondition *wcd;
    static std::queue<std::pair<QString,int>>*q;//ip port
    static std::deque<int>*rand_q;//random deque to improve the effecience
    static std::pair<QString,int> get_from_queue()
    {
        if(q->size()==0)return {" ",-1};
        auto x=q->front();
        q->pop();
        return x;
    }
    static bool paused,stopped;
    static int get_rand()
    {
        int x=rand_q->front();
        rand_q->pop_front();
        rand_q->push_back(x);
        return x;
    }//get random number from deque
    static std::pair<int,std::vector<std::vector<std::pair<QString,int>>>> init(QStringList ip_list,std::pair<int,int>conseq_ports,std::vector<int>ports,int base_time,int thread_cnt)
    {
        mutex=new QMutex;
        wcd=new QWaitCondition;
        //return the sum of task;
        int ip_port_cnt=0;
        std::srand(static_cast<unsigned int>(std::time(nullptr)));
        q=new std::queue<std::pair<QString,int>>;
        rand_q=new std::deque<int>;
        paused=stopped=false;
        //ip port part:
        for(auto x:ip_list){
            std::unordered_map<int,bool>p_exi;
            ip_port_cnt+=conseq_ports.second-conseq_ports.first+1;
            for(int i=conseq_ports.first;i<=conseq_ports.second;i++){
                q->push({x,i});
                p_exi[i]=true;
            }
            for(int y:ports){
                if(p_exi[y])continue;
                q->push({x,y});
                p_exi[y]=true;
                ip_port_cnt++;
            }
        }
        //分配线程任务
        int per_sum=ip_port_cnt/thread_cnt+1;
        std::vector<std::vector<std::pair<QString,int>>>tasks;
        tasks.resize(thread_cnt);
        int res(0);
        for(int i=0;i<thread_cnt;i++){
            while(q->size()&&res<per_sum){
                tasks[i].push_back(q->front());
                q->pop();
                res++;
            }
            res=0;
        }
        //random part:
        for(int i=0;i<thread_cnt+2;i++){
            int f=rand()%(thread_cnt*20);
            if(f&1){
                rand_q->push_back(rand()%(((thread_cnt>>1)*(thread_cnt>>1))*2)+base_time);
            }else{
                rand_q->push_front(rand()%(((thread_cnt>>1)*(thread_cnt>>1))*2)+base_time);
            }
        }
        return {ip_port_cnt,tasks};
    }
    static void sc_pause();
    static void sc_preceed();
    static void sc_stop();
    using callback=std::function<void(std::pair<std::pair<QString,int>,std::pair<QString,bool>>)>;//ip port category up/down
    scan_thread(callback cb)
    {
        //tcp udp part:
        tcp_tool=new QTcpSocket;
        udp_tool=new QUdpSocket;
        tcp_tool->moveToThread(this);
        //udp_tool->moveToThread(this);
        //randon num part:
        rand_num=300;//basic wait time
        //callback:
        sc_cb=cb;
        //first pause set
        first_pause=true;
    }
signals:
    void has_paused();
    void has_stopped();
    void has_started();
private:
    int rand_num;//while run use this as the rand num for msleep
    QTcpSocket *tcp_tool;
    QUdpSocket *udp_tool;
    callback sc_cb;
    bool first_pause;
    std::vector<std::pair<QString,int>>mytask;
    // QThread interface
public:
    void run();
    void setRand_num(int newRand_num);
    void setMytask(const std::vector<std::pair<QString, int> > newMytask);
};

#endif // SCAN_THREAD_H
